<script setup lang="ts">
import { getNeed, ProcessType, useStore } from "~/models/data";
import { storeToRefs } from "pinia";
import { ElMessage } from "element-plus";
import { compareArrByEachElement, sToNumArr, testStringAllNumber } from "~/utils/funcs";

enum InputType {
  Max,
  Allocation,
}

const { processNum, resourceNum, avaliable, process } = storeToRefs(useStore())

type ProcessFormType = {
  pid: string;
  max: string;
  need: string;
  allocation: string;
  status: false;
}


const processForm = ref<ProcessFormType[]>([])
const av = ref('')

let tmparr: ProcessFormType[] = []
for (let i = 0; i < processNum.value; ++i) {
  tmparr = [...tmparr, {
    pid: `p${i}`,
    max: '',
    need: '',
    allocation: '',
    status: false,
  }]
}
processForm.value = tmparr

const router = useRouter()

const avFlag = ref(false)


function alertCheckError(msg: string) {
  ElMessage({
    message: msg,
    type: 'error'
  })
}

function checkAvaliable() {
  if (av.value === '') {
    return
  }
  const av_arr = av.value.trim().split(' ')
  if (testStringAllNumber(av_arr, resourceNum.value)) {
    avFlag.value = true
  } else {
    avFlag.value = false
    av.value = ''
    alertCheckError('数据格式有误')
  }
}

function maxGtAllo() {
  let flag = true
  processForm.value.forEach(it => {
    const max_arr = it.max === '' ? Array.from({ length: resourceNum.value }, () => 0) : sToNumArr(it.max)
    const allo_arr = it.allocation === '' ? Array.from({ length: resourceNum.value }, () => 0) : sToNumArr(it.allocation)
    if (!compareArrByEachElement(max_arr, allo_arr)) {
      flag = false
    }
  })
  return flag
}

function checkProcessCount() {
  let maxCnt = 0
  let alloCnt = 0
  processForm.value.forEach(it => {
    if (it.max === '' || it.allocation === '') {
      return false
    }
    if (it.max !== '') {
      maxCnt++
    }
    if (it.allocation !== '') {
      alloCnt++
    }
  })
  return maxCnt === processNum.value && alloCnt === processNum.value
}

function checkValid(rowId: number, inputType: InputType) {
  let flag = true
  const location = inputType === InputType.Allocation ? 'allocation' : 'max'
  if (processForm.value[rowId][location] === '') {
    return
  }
  const value = processForm.value[rowId][location].trim().split(' ')

  if (!testStringAllNumber(value, resourceNum.value)) {
    alertCheckError('数据格式错误')

    flag = false
  } else if (!maxGtAllo()) {
    alertCheckError('分配的allocation大于max')
    flag = false
  }
  if (!flag) {
    processForm.value[rowId][location] = ''
  }
}

function go() {
  if (!avFlag.value || !checkProcessCount()) {
    alertCheckError("数据不完整")
    return
  }
  processForm.value = processForm.value.map(it => {
    const item: ProcessType = {
      pid: it.pid,
      max: sToNumArr(it.max),
      need: [],
      allocation: sToNumArr(it.allocation),
      status: it.status
    }
    const s = getNeed(item).join(' ')
    return {
      ...it,
      need: s,
      status: false
    }
  })
  process.value = processForm.value.map(it => ({
    pid: it.pid,
    max: sToNumArr(it.max),
    need: sToNumArr(it.need),
    allocation: sToNumArr(it.allocation),
    status: it.status
  }))
  avaliable.value = sToNumArr(av.value)
  router.push('/three')
}

</script>

<template>
  <div flex="~ col" justify-center items-center>
    <p text-3xl text-blue-500>银行家算法-输入当前系统状态的数据</p>
    <div py-4 />
    <div>
      <strong>进程数：{{ processNum }}</strong>&nbsp;
      <strong>资源种类数：{{ resourceNum }}</strong>&nbsp;
      <strong>资源剩余数(available)：</strong>
      <input v-model="av" @blur="checkAvaliable" placeholder="例：2 3 3" type="text" autocomplete="false" p="x-4 y-2" w="250px" bg="transparent"
        border="~ rounded gray-200 dark:gray-700" outline="none active:none">
    </div>

    <br>
    <el-table class="flex justify-center" :data="processForm" style="width: 540px" :key="Math.random()">
      <el-table-column prop="pid" label="进程" width="80" />
      <el-table-column prop="max" label="Max" width="100">
        <template #default="scope">
          <el-input v-model="scope.row.max" @blur="() => checkValid(scope.$index, InputType.Max)" />
        </template>
      </el-table-column>
      <el-table-column prop="allocation" label="Allocation" width="100">
        <template #default="scope">
          <el-input v-model="scope.row.allocation" @blur="() => checkValid(scope.$index, InputType.Allocation)" />
        </template>
      </el-table-column>
    </el-table>

    <div>
      <button class="btn m-3 text-sm" @click="go">下一步</button>
    </div>
  </div>
</template>
